roman_list = ['I', 'V', 'X', 'L', 'C', 'D', 'M'];

def distance(cur, target):
    distance = roman_list.index(target) - roman_list.index(cur);
    return distance;

def getPower(letter):
    power_list = [1, 5, 10, 50, 100, 500, 1000];
    index = roman_list.index(letter);
    return power_list[index];

def regularConvert(rom):
    """

    convert Roman digits > 0 and <= 3999 to integer
    regular convert without validity checking

    :type rom : str
    :rtype int
    """
    if len(rom) == 0:
        print('Roman should larger than 0');
        return 0;

    num = 0;
    for i in range(0, len(rom)):
        let = rom[i];
        if i + 1 < len(rom):
            dis = distance(let, rom[i + 1]);
            if dis > 0: 
                num -= getPower(let);
            elif dis <= 0:
                num += getPower(let);
        else:
            num += getPower(let);
    return num;

roman_unit = ['I', 'X', 'C', 'M'];
dict_units = {'I':'II', 'V':'I', 'X':'IX', 'L':'X', 'C':'XC', 'D':'C', 'M':'CM'};

def isValid(letter):
    return roman_list.count(letter) > 0;

def isUnit(letter): # [1, 3]*letter can be added
    return roman_unit.count(letter) > 0;

def canCat(letA, letB):
    return dict_units.get(letA).count(letB) > 0;

def convert(rom):
    """

    convert Roman digits > 0 and <= 3999 to integer

    :type rom : str
    :rtype int
    """
    if len(rom) == 0:
        print('Roman should larger than 0');
        return 0;

    num = 0;
    index = 0;
    repeat = 1;
    nextL = '';
    for i in range(0, len(rom)):
        let = rom[i];
        if not isValid(let):
            print('Invalid type A: invalid char', let);
            return None;

        if i + 1 < len(rom):
            nextL = rom[i + 1];
        else:
            num += regularConvert(rom[index : i+1]);
            index = i+1;
            break;

        is_unit = isUnit(let);
        is_next_unit = isUnit(nextL);
        if not is_unit:
            if i > 0 and nextL == rom[i - 1]: # IVI, CLC, MDM 
                print('Invalid type B: invalid seq', rom[i-1:i+2]);
                return None;
            dist = distance(let, nextL);
            if not is_next_unit and dist >= 0: # LD, VL, VV, LL, DD
                print('Invalid type C: invalid seq', rom[i:i+2]);
                return None;
            elif is_next_unit:
                if dist > 0: # LM, VC
                    print('Invalid type D: invalid seq', rom[i:i+2]);
                    return None;
                else:
                    num += regularConvert(rom[index : i+1]);
                    index = i+1;
            else:
                num += regularConvert(rom[index : i+1]);
                index = i+1;
        else:
            dist = distance(let, nextL);
            if is_next_unit:
                if dist == 0:
                    if repeat == 3: # IIII
                        print('Invalid type E: >3 same letters');
                        return None;
                elif dist > 0:
                    if not canCat(nextL, let):# XM, IC
                        print('Invalid type F: invalid seq', rom[i:i+2]);
                        return None;
                elif i > 0 and nextL == rom[i - 1]: # CMC, XIX
                    print('Invalid type B: invalid seq', rom[i-1:i+2]);
                    return None;
                else:
                    num += regularConvert(rom[index : i+1]);
                    index = i+1;
            else:
                if i > 0 and nextL == rom[i - 1]: # LCL, VIV
                    print('Invalid type B: invalid seq', rom[i-1:i+2]);
                    return None;

                if dist > 0:
                    if not canCat(nextL, let):# XD, IL
                        print('Invalid type D: invalid seq', rom[i:i+2]);
                        return None;
                elif dist == -1 and i > 0 and repeat == 1 and canCat(let, rom[i - 1]):# XCL, IXV, CMD
                    print('Invalid type B: invalid seq', rom[i-1:i+2]);
                    return None;
        if nextL == let:
            repeat += 1;
        else:
            repeat = 1;
    return num;
